﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace NetworkSimulator
{
    public class ReleaseManager:ITickerListener
    {
        // Synchronize object
        private static object lockingObject = new object();

        private static ReleaseManager singleTonObject;
        private Ticker ticker;
        private List<Release> releaseList;
        private List<Release> results;

        public List<Release> ReleaseList
        {
            get { return releaseList; }
        }

        public static ReleaseManager instance()
        {
            if (singleTonObject == null)
            {
                lock (lockingObject)
                {
                    if (singleTonObject == null)
                        singleTonObject = new ReleaseManager();
                }
            }
            return singleTonObject;
        }

        public ReleaseManager()
        {
            ticker = Ticker.instance();
            ticker.addListener(this);
            releaseList = new List<Release>();
            results = new List<Release>();
            Thread.CurrentThread.Priority = ThreadPriority.Highest;
        }

        public void push(Release release)
        {
            lock (lockingObject)
            {
                release.ReleasingTime = ticker.ElapsedTime + release.HoldingTime;
                releaseList.Add(release);
                releaseList =  releaseList.OrderBy(o => o.ReleasingTime).ToList();
            }
        }

        public void onTickerTick()
        {
            if (releaseList.Count > 0)
            {
                Release release = releaseList[0];
                while (release.ReleasingTime <= ticker.ElapsedTime)
                {
                    doRelease(release);
                    releaseList.RemoveAt(0);
                    if (releaseList.Count == 0) break;
                    release = releaseList[0];
                }
            }
        }

        private void doRelease(Release release)
        {
            lock (Topology.lockingObject)
            {
                Console.WriteLine(release);
                foreach (Link link in release.Path.Links)
                {
                    link.Bandwidth -= release.HoldingBandwidth;
                }
            }
            results.Add(release);
            if (results.Count == RequestDispatcher.instance().NumOfRequest)
            { 
                //TODO:
                ticker.stop();
            }
        }
    }
}
